/*
	File:		Entity.cpp
	Author:		dmonroe
	Date:		11/27/2012
	Copyright:	Full Sail University

	Purpose:	Base class for game objects
*/

#include "../source/Entity.h"
#include "../source/EntityType.h"

#include "../source/EntityController.h"
#include "../source/EntityController_Actions.h"

#include "../source/Constants.h"
#include "../source/IGraphics.h"

#include <cassert>


//******************************************************************
// CONSTRUCTOR
CEntity::CEntity( void )
{
	m_pController		= NULL;

	m_hImage			= HTexture();

	m_fPositionX		= 0.0f;
	m_fPositionY		= 0.0f;
		
	m_fVelocityX		= 0.0f;
	m_fVelocityY		= 0.0f;
		
	m_ulWidth			= 1;
	m_ulHeight			= 1;
	
	m_ulReferenceCount	= 1;
}
//******************************************************************



//******************************************************************
// DESTRUCTOR
CEntity::~CEntity(void)
{
	SetController( NULL );
}
//******************************************************************



//******************************************************************
// INPUT
/*virtual*/ void CEntity::Input( float fElapsedTime )
{
	// Is there a logic controller?
	if( m_pController != NULL )
	{
		// Update the logic controller
		m_pController->Update( this, fElapsedTime );

		// Is there anything we should know about?
		if( m_pController->ShouldPerform( this ) )
		{
			// HACK: Should store acceleration & max velocity as data members
			float acc = 50;
			// Check for CEntity behavior
			float move = m_pController->ShouldPerformAction( this, E_EACT_MOVE_LEFT );
			if( move > 0.0f )
				m_fVelocityX -= move * acc * fElapsedTime;
			
			move = m_pController->ShouldPerformAction( this, E_EACT_MOVE_RIGHT );
			if( move > 0.0f )
				m_fVelocityX += move * acc * fElapsedTime;
			
			move = m_pController->ShouldPerformAction( this, E_EACT_MOVE_UP );
			if( move > 0.0f )
				m_fVelocityY -= move * acc * fElapsedTime;
			
			move = m_pController->ShouldPerformAction( this, E_EACT_MOVE_DOWN );
			if( move > 0.0f )
				m_fVelocityY += move * acc * fElapsedTime;
		}
	}
}
//******************************************************************



//******************************************************************
// UPDATE
/*virtual*/ void CEntity::Update( float fElapsedTime )
{
	m_fPositionX += m_fVelocityX * fElapsedTime;
	m_fPositionY += m_fVelocityY * fElapsedTime;
}
//******************************************************************



//******************************************************************
// RENDER
/*virtual*/ void CEntity::Render( float fElapsedTime )
{
	(void)fElapsedTime;	// unused for now

	IGraphics::GetInstance()->DrawTexture( m_hImage, (int)m_fPositionX, (int)m_fPositionY );
}
//******************************************************************



//******************************************************************
// GETTYPE
/*virtual*/ int CEntity::GetType( void )
{
	return E_ENTITY;
}
//******************************************************************



//******************************************************************
// ISCOLLIDABLE
/*virtual*/ bool CEntity::IsCollidable( void )
{
	return true;
}
//******************************************************************



//******************************************************************
// ONCOLLISION
/*virtual*/ bool CEntity::OnCollision( const IEntity* pOther )
{
	return false;
}
//******************************************************************



//******************************************************************
// ADDREF
/*virtual*/ void CEntity::AddRef( void )
{
	++m_ulReferenceCount;
}
//******************************************************************



//******************************************************************
// RELEASE
/*virtual*/ void CEntity::Release( void )
{
	--m_ulReferenceCount;

	if( m_ulReferenceCount == 0 )
		delete this;
}
//******************************************************************



//******************************************************************
// GETRECT
/*virtual*/ SRect CEntity::GetRect( void ) const
{
	SRect rBoundingBox = { };

	rBoundingBox.left	= (long)m_fPositionX;
	rBoundingBox.top	= (long)m_fPositionY;

	rBoundingBox.right	= rBoundingBox.left	+ (long)m_ulWidth;
	rBoundingBox.bottom	= rBoundingBox.top	+ (long)m_ulHeight;

	return rBoundingBox;
}
//******************************************************************



//******************************************************************
// SET CONTROLLER
void CEntity::SetController( CEntityController* p )
{
	if( m_pController != NULL )
		m_pController->Release();

	m_pController = p;

	if( m_pController != NULL )
		m_pController->AddRef();
}
//******************************************************************



//******************************************************************
// ISCOLLIDING
/*friend*/ bool IsColliding( const IEntity* pEntity1, const IEntity* pEntity2)
{
	assert( dynamic_cast< const CEntity* >( pEntity1 ) != NULL
			&& dynamic_cast< const CEntity* >( pEntity2 ) != NULL
			&& "Entity.cpp : IsColliding - parameters are not CEntity objects!" != 0 );

	return IntersectRect( ((CEntity*)pEntity1)->GetRect(), ((CEntity*)pEntity2)->GetRect() );

}
//******************************************************************
